//C- -------------------------------------------------------------------
//C- Java DjVu (r) (v. 0.8)
//C- Copyright (c) 2004-2005 LizardTech, Inc.  All Rights Reserved.
//C- Java DjVu is protected by U.S. Pat. No.C- 6,058,214 and patents
//C- pending.
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, Version 2. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- The computer code originally released by LizardTech under this
//C- license and unmodified by other parties is deemed "the LIZARDTECH
//C- ORIGINAL CODE."  Subject to any third party intellectual property
//C- claims, LizardTech grants recipient a worldwide, royalty-free,
//C- non-exclusive license to make, use, sell, or otherwise dispose of
//C- the LIZARDTECH ORIGINAL CODE or of programs derived from the
//C- LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
//C- General Public License.   This grant only confers the right to
//C- infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
//C- the extent such infringement is reasonably necessary to enable
//C- recipient to make, have made, practice, sell, or otherwise dispose
//C- of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
//C- any greater extent that may be necessary to utilize further
//C- modifications or combinations.
//C-
//C- The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C-
//C- In addition, as a special exception, LizardTech Inc. gives permission
//C- to link the code of this program with the proprietary Java
//C- implementation provided by Sun (or other vendors as well), and
//C- distribute linked combinations including the two. You must obey the
//C- GNU General Public License in all respects for all of the code used
//C- other than the proprietary Java implementation. If you modify this
//C- file, you may extend this exception to your version of the file, but
//C- you are not obligated to do so. If you do not wish to do so, delete
//C- this exception statement from your version.
//C- -------------------------------------------------------------------
//C- Developed by Bill C. Riemers, Foxtrot Technologies Inc. as work for
//C- hire under US copyright laws.
//C- -------------------------------------------------------------------
//
package com.lizardtech.djvubean.toolbar;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.reflect.*;
import java.lang.reflect.Array;
import java.net.URL;
import java.util.*;


/**
 * This class implements support for ItemListeners and ActionListeners.
 *
 * @author Bill C. Riemers
 * @version $Revision: 1.3 $
 */
public class ListenerSupport
{
  //~ Instance fields --------------------------------------------------------

  /** Class this is intended to support. */
  private final Class listenerClass;

  /** A map of Listeners. */
  private final Hashtable map = new Hashtable();

  /** Cache array of Listener objects. */
  private Object array = null;

  //~ Constructors -----------------------------------------------------------

  /**
   * Creates a new ListenerSupport object.
   *
   * @param listenerClass Either ItemListener.class or ActionListener.class
   */
  public ListenerSupport(final Class listenerClass)
  {
    this.listenerClass = listenerClass;
  }

  //~ Methods ----------------------------------------------------------------

  /**
   * Query currently registered ItemListener objects.
   *
   * @return array of ItemListener objects.
   */
  public Object getListeners()
  {
    Object retval = array;

    if(retval == null)
    {
      synchronized(map)
      {
        retval = array;

        if(retval == null)
        {
          int length = map.size();
          retval = Array.newInstance(listenerClass, length);

          int i = 0;

          for(
            Enumeration e = map.elements();
            (i < length) && e.hasMoreElements();)
          {
            Array.set(
              retval,
              i++,
              e.nextElement());
          }
        }
      }
    }

    return retval;
  }

  /**
   * Add a new Listener.
   *
   * @param listener to add.
   */
  public void addListener(final Object listener)
  {
    if(listenerClass.isInstance(listener))
    {
      synchronized(map)
      {
        array = null;
        map.put(listener, listener);
      }
    }
  }

  /**
   * Calls the actionPerformed(event) method for all listeners.
   *
   * @param event The ActionEvent generated by the class we are listening to.
   */
  public void fireActionEvent(final ActionEvent event)
  {
    final ActionListener[] array = (ActionListener[])getListeners();

    if(array != null)
    {
      for(int i = 0; i < array.length;)
      {
        array[i++].actionPerformed(event);
      }
    }
  }

  /**
   * Called to send Events.
   *
   * @param event The ItemEvent generated by the class we are listening to.
   */
  public void fireItemEvent(final ItemEvent event)
  {
    final ItemListener[] array = (ItemListener[])getListeners();

    if(array != null)
    {
      for(int i = 0; i < array.length;)
      {
        array[i++].itemStateChanged(event);
      }
    }
  }

  /**
   * Remove a Listener.
   *
   * @param listener to remove.
   */
  public void removeListener(final Object listener)
  {
    if(listener != null)
    {
      synchronized(map)
      {
        array = null;
        map.remove(listener);
      }
    }
  }
}
